/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Blackjack;

import java.util.List;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import prop.Carta;
/**
 *
 * @author Michal
 */

// Faltan ciertas funcionalidades, como detectar y eliminar a un jugador
// que se ha retirado o perdido y detectar el fin de sesion.
public class DriverDomainSesion {
    private SesionBkjk sesion;
    private DataManagerSesion DMS;

    public DriverDomainSesion() {

    }

  // Los dos primeros elementos de la lista param son NumBarajas y NumJugadores
  // A continuacion vienen las caracteristicas de cada jugador:
  // es_maquina? nombre dinero nombreEstrategia    -  Si es maquina
  // es_maquina? nombre dinero                     -  Si es humano
    
    public String iniciarSesion(List param) {
        ConfiguracionBkjk conf = new ConfiguracionBkjk((String)param.remove(0));
        conf.setInt("NumBarajas", (Integer)param.remove(0));
        conf.setInt("NumJugadores", (Integer)param.remove(0));
        sesion = new SesionBkjk(conf);
        int mod = (Integer)param.remove(0);
        conf.setInt("Modalidad", mod);
        if (mod == 0) conf.setInt("Coeficiente", (Integer)param.remove(0));
        else if(mod == 1) conf.setInt("LimManos", (Integer)param.remove(0));
        int din = (Integer)param.remove(0);
        conf.setInt("DineroInicial", din);
        for (int i = 0; i < conf.getInt("NumJugadores"); ++i) {
            JugadorBkjk jug = null;
            if ((Boolean)param.remove(0) == true) {
                jug = new JugadorMaquinaBkjk(true);

                jug.setNombre((String)param.remove(0));
                jug.setDinero(din);
                String nombre = (String)param.remove(0);
                DataManagerEstrategiaBkjk lee =
                new DataManagerEstrategiaBkjk(nombre);
                EstrategiaBkjk estr = new EstrategiaBkjk();
                try {
                    lee.leerEstrategia(estr);
                }
                catch (Exception e) {
                    return nombre;
                }
                estr.setJugador(jug);
                estr.setMesa(sesion.getMesa());
                ((JugadorMaquinaBkjk) jug).setEstrategia(estr);
            }
            else {
                jug = new JugadorBkjk(false);
                jug.setNombre((String)param.remove(0));
                jug.setDinero(din);
            }
            sesion.getMesa().anadirJugador(jug);
        }
        return null;
    }

    public List cargarSesion(String path) {
        DMS = new DataManagerSesion();
        sesion = DMS.cargarSesion(path);
        List l = new ArrayList();
        if (sesion == null) {
            l.add(-1);
            return l;
        }
        l.add((Integer)sesion.getMesa().getJugadores().size());
        for (int i = 0; i < sesion.getMesa().getJugadores().size(); i++) {
            l.add(sesion.getMesa().getJugador(i).getNombre());
            l.add(sesion.getMesa().getJugador(i).getDinero());
        }
        return l;
    }

    public void borrarSesion(String path) {
        DMS = new DataManagerSesion();
        DMS.borrarSesion(path);
    }

    public void guardarSesion(String path) {
        DMS = new DataManagerSesion();
        DMS.guardarSesion(path, sesion);
    }

    public boolean esMaquina(int jugador) {
        return sesion.getMesa().getJugador(jugador).esMaquina();
    }

    public boolean apostar(int jugador, int dinero) {
        boolean puede =
                sesion.getMesa().getJugador(jugador).getDinero() >= dinero;
        if (puede) {
            sesion.getMesa().getJugador(jugador).
                    getJugadaActual().setApuesta(dinero);
            sesion.getMesa().getJugador(jugador).restarDinero(dinero);
        }
        return puede;
    }

    public int apostarMaquina(int jugador) {
        JugadorMaquinaBkjk jug = (JugadorMaquinaBkjk) sesion.getMesa().getJugador(jugador);
        int ap;
        if (jug.pedirApuesta().getNombre().equals("apostar")) {
            ap = jug.getEstrategia().getInt(jug.pedirApuesta().getParametro(0));
            boolean puede = jug.getDinero() >= ap && ap > 0;
            if (!puede) ap = jug.getDinero();
        }
        else ap = jug.getDinero();
        jug.setDinero(jug.getDinero() - ap);
        jug.getJugadaActual().setApuesta(ap);
        return ap;
    }

    public boolean apostarSeguro(int jugador, int dinero) {
        boolean puede =
                sesion.getMesa().getJugador(jugador).getDinero() >= dinero;
        if (puede) {
            sesion.getMesa().getJugador(jugador).setSeguro(dinero);
            sesion.getMesa().getJugador(jugador).restarDinero(dinero);
        }
        return puede;
    }

    public int apostarSeguroMaquina(int jugador) {
        JugadorMaquinaBkjk jug =
                (JugadorMaquinaBkjk) sesion.getMesa().getJugador(jugador);
        int ap;
        if (jug.pedirSeguro().getNombre().equals("seguro")) {
            ap = jug.getEstrategia().getInt(jug.pedirSeguro().getParametro(0));
            boolean puede = jug.getDinero() >= ap;
            if (!puede) ap = jug.getDinero();
        }
        else ap = 0;
        jug.setDinero(jug.getDinero() - ap);
        jug.setSeguro(ap);
        return ap;
    }

    public List iniciarJuego(int jugador) {
        List l = new ArrayList();
        Carta c1 = sesion.getMesa().getBaraja().sacarCarta();
        Carta c2 = sesion.getMesa().getBaraja().sacarCarta();
        sesion.getMesa().getJugador(jugador).
                getJugadaActual().getMano().iniciarMano(c1, c2);
        l.add(getPalo(c1));
        l.add(c1.getNum());
        l.add(getPalo(c2));
        l.add(c2.getNum());
        return l;
    }

    public List iniciarJuegoCoupier() {
        List l = new ArrayList();
        Carta c1 = sesion.getMesa().getBaraja().sacarCarta();
        Carta c2 = sesion.getMesa().getBaraja().sacarCarta();
        sesion.getMesa().getCroupier().getMano().iniciarManoCroupier(c1, c2);
        l.add(getPalo(c1));
        l.add(c1.getNum());
        l.add(getPalo(c2));
        l.add(c2.getNum());
        return l;
    }

    public boolean tieneAsCroupier() {
        return sesion.getMesa().getCroupier().
                getMano().getCarta(1).getNum() == 1;
    }

    public void mostrarCartaCroupier() {
        sesion.getMesa().getCroupier().getMano().mostrarCartaCroupier();
    }

    public boolean blackjackCroupier() {
        return (sesion.getMesa().getCroupier().getMano().getNumCartas() == 2
            && sesion.getMesa().getCroupier().getMano().evaluar()%100 == 21);
    }

    public void ganarSeguro(int jugador) {
        JugadorBkjk jug = sesion.getMesa().getJugador(jugador);
        jug.setDinero(jug.getDinero() + jug.getSeguro()*2); // es *2 no?
    }

    public boolean blackjack(int jugador) {
        JugadorBkjk jug = sesion.getMesa().getJugador(jugador);
        if (jug.getJugadaActual().getMano().getNumCartas() == 2
            && jug.getJugadaActual().getMano().evaluar()%100 == 21) {
            if (!blackjackCroupier()) {
                jug.setDinero(jug.getDinero() + (5*jug.getJugadaActual().getApuesta())/2);
            }
            jug.pasarJugada();
            return true;
        }
        return false;
    }

    public List jugadaCroupier() {
        List l = new ArrayList();
        if (sesion.getMesa().getCroupier().getMano().evaluar()%100 < 17) {
            Carta c = sesion.getMesa().getBaraja().sacarCarta();
            sesion.getMesa().getCroupier().getMano().anadirCarta(c);
            l.add(getPalo(c));
            l.add(c.getNum());
        }
        return l;
    }

    public boolean haTerminadoCroupier() {
        return sesion.getMesa().getCroupier().getMano().evaluar()%100 >= 17;
    }

    public boolean puedeDoblar(int jugador) {
        return (sesion.getMesa().getJugador(jugador).
                getJugadaActual().getMano().getNumCartas() == 2
           && sesion.getMesa().getJugador(jugador).getDinero()
           >= sesion.getMesa().getJugador(jugador).
           getJugadaActual().getApuesta());
    }

    public boolean puedeDividir(int jugador) {
       return (sesion.getMesa().getJugador(jugador).getJugadasActivas() < 4
           && sesion.getMesa().getJugador(jugador).
           getJugadaActual().getMano().evaluar() > 200
           && sesion.getMesa().getJugador(jugador).getDinero()
           >= sesion.getMesa().getJugador(jugador).
           getJugadaActual().getApuesta());
    }

    public int getJugadaUltima(int jugador) {
        return sesion.getMesa().getJugador(jugador).getJugadasActivas();
    }



    public List pasar(int jugador) {
        sesion.getMesa().getJugador(jugador).pasarJugada();
        List l = new ArrayList();
        int id = 0;
        l.add(id);
        return l;
    }

    public List pedir(int jugador) {
        Carta c = sesion.getMesa().getBaraja().sacarCarta();
        sesion.getMesa().getJugador(jugador).
                getJugadaActual().getMano().anadirCarta(c);
        List l = new ArrayList();
        int id = 1;
        l.add(id);
        l.add(getPalo(c));
        l.add(c.getNum());
        return l;
    }

    public List dividir(int jugador) {
        List l = new ArrayList();
        int id = 2;
        l.add(id);
        int palo;
        if (puedeDividir(jugador)) {
            Carta c1 = sesion.getMesa().getJugador(jugador).
                    getJugadaActual().getMano().sacarCarta();
            l.add(getPalo(c1));
            l.add(c1.getNum());
            Carta c2 = sesion.getMesa().getBaraja().sacarCarta();
            l.add(getPalo(c2));
            l.add(c2.getNum());
            sesion.getMesa().getJugador(jugador).
                    getJugadaActual().getMano().anadirCarta(c2);
            c2 = sesion.getMesa().getBaraja().sacarCarta();
            l.add(getPalo(c2));
            l.add(c2.getNum());
            sesion.getMesa().getJugador(jugador).
                    empezarOtraJugada().getMano().iniciarMano(c1, c2);
            int n = sesion.getMesa().getJugador(jugador).
                    getJugadaActual().getApuesta();
            sesion.getMesa().getJugador(jugador).restarDinero(n);
        }
        return l;
    }

    public List doblar(int jugador) {
        List l = new ArrayList();
        int id = 3;
        l.add(id);
        int palo;
        if (puedeDoblar(jugador)) {
            int n = sesion.getMesa().getJugador(jugador).
                    getJugadaActual().getApuesta();
            sesion.getMesa().getJugador(jugador).restarDinero(n);
            sesion.getMesa().getJugador(jugador).
                    getJugadaActual().doblarApuesta();
            Carta c = sesion.getMesa().getBaraja().sacarCarta();
            l.add(getPalo(c));
            l.add(c.getNum());
            sesion.getMesa().getJugador(jugador).
                    getJugadaActual().getMano().anadirCarta(c);
            sesion.getMesa().getJugador(jugador).pasarJugada();
        }
        return l;
    }

    public List accionMaquina(int jugador) {
        JugadorMaquinaBkjk jug =
                (JugadorMaquinaBkjk) sesion.getMesa().getJugador(jugador);
        String acc = jug.getEstrategia().actuar().getNombre();
        if (acc.equals("pasar")) return pasar(jugador);
        else if (acc.equals("pedir")) return pedir(jugador);
        else if (acc.equals("dividir")) return dividir(jugador);
        else if (acc.equals("doblar")) return doblar(jugador);
        else return pasar(jugador);
    }

     public boolean manoPasada(int jugador, int mano) {
         if  (sesion.getMesa().getJugador(jugador).getJugada(mano).getMano().evaluar()%100 >= 21) {
             sesion.getMesa().getJugador(jugador).pasarJugada();
             return true;
         }
         return false;
     }

    public boolean haTerminado(int jugador) {
        return sesion.getMesa().getJugador(jugador).haTerminado();
    }

    public int haGanado(int jugador, int mano) {
        Jugada jug = sesion.getMesa().getJugador(jugador).getJugada(mano);
        if (jug.getMano().evaluar()%100 > 21) return -1;
        else if (sesion.getMesa().getCroupier().getMano().evaluar()%100 > 21
                || sesion.getMesa().getCroupier().getMano().evaluar()%100 <
                jug.getMano().evaluar()%100) {
            sesion.getMesa().getJugador(jugador).setDinero(sesion.getMesa().getJugador(jugador).getDinero() + 2*jug.getApuesta());
            return 1;
        }
            else if (sesion.getMesa().getCroupier().getMano().evaluar()%100 ==
                jug.getMano().evaluar()%100) {
            sesion.getMesa().getJugador(jugador).setDinero(sesion.getMesa().getJugador(jugador).getDinero() + jug.getApuesta());
            return 0;
        }
        return -1;
    }

    public void finPartida() {
        Carta c;
        while(sesion.getMesa().getCroupier().getMano().getNumCartas() > 0) {
            c = sesion.getMesa().getCroupier().getMano().sacarCarta();
            c.ocultar();
            sesion.getMesa().getBaraja().anadirCarta(c);
        }
        for (int i = 0; i < sesion.getMesa().getNumJugadores(); i++) {
            for (int j = 0; j < sesion.getMesa().
                    getJugador(i).getJugadasActivas(); j++) {
                while(sesion.getMesa().getJugador(i).
                        getJugada(j).getMano().getNumCartas() > 0) {
                    c = sesion.getMesa().getJugador(i).
                            getJugada(j).getMano().sacarCarta();
                    c.ocultar();
                    sesion.getMesa().getBaraja().anadirCarta(c);
                    sesion.getMesa().getJugador(i).getJugada(j).setApuesta(0);
                }
            }
            sesion.getMesa().getJugador(i).resetJugadas();
            sesion.getMesa().getJugador(i).setSeguro(0);
        }
        sesion.getMesa().getBaraja().barajar();
        sesion.incrNumPartidas();
    }

    public boolean haPerdido(int jugador) {
        JugadorBkjk j = sesion.getMesa().getJugador(jugador);
        if (j.getDinero() == 0) {
            sesion.getMesa().quitarJugador(j);
            return true;
        }
        else return false;
    }

    public void retirar(int jugador) {
        JugadorBkjk j = sesion.getMesa().getJugador(jugador);
        int res = 0;
        int mod = sesion.getConf().getInt("Modalidad");
        switch (mod) {
            case 0://Con limite de dinero
                break;
            case 1: // con limite de manos
                res = j.getDinero()/sesion.getConf().getInt("LimManos");
                break;
            case 2: // modalidad libre
                res = j.getDinero();
                break;
        }
        if (res != 0) sesion.addResultado(j.getNombre(), res);
        sesion.getMesa().quitarJugador(j);
    }

    public boolean haAcabado() {
        int mod = sesion.getConf().getInt("Modalidad");
        boolean acabado = false;
        switch (mod) {
            case 0:
                int lim = sesion.getConf().getInt("Coeficiente")*sesion.getConf().getInt("DineroInicial");
                int i = 0;
                int njug = sesion.getMesa().getJugadores().size();
                while (!acabado && i < njug) {
                    if (sesion.getMesa().getJugador(i).getDinero() >= lim) acabado = true;
                    else i++;
                }
                if (acabado) {
                    int punt = (1000*sesion.getConf().getInt("Coeficiente"))/sesion.getNumPartidas();
                    sesion.addResultado(sesion.getMesa().getJugador(i).getNombre(), punt);
                }
                break;
            case 1:
                acabado = sesion.getNumPartidas() == sesion.getConf().getInt("LimManos");
                break;
        }
        if (sesion.getMesa().getJugadores().size() == 0) acabado = true;
        return acabado;
    }

    public List acabar() {
        int mod = sesion.getConf().getInt("Modalidad");
        switch(mod) {
            //FALTA case 0 NO? -Re: NO, no hace falta, cuando se comprueba si se ha acabado, ya se pone el jugador que ha ganado en la lista
            case 0:
                break;
            case 1:
                for (int i = 0; i < sesion.getMesa().getJugadores().size(); i++) {
                    if (!sesion.getMesa().getJugador(i).esMaquina()) {
                        int punt = sesion.getMesa().getJugador(i).getDinero()/sesion.getConf().getInt("LimManos");
                        sesion.addResultado(sesion.getMesa().getJugador(i).getNombre(), punt);
                    }
                }
                break;
            case 2:
                for (int i = 0; i < sesion.getMesa().getJugadores().size(); i++) {
                    if (!sesion.getMesa().getJugador(i).esMaquina()) {
                        int punt = sesion.getMesa().getJugador(i).getDinero();
                        sesion.addResultado(sesion.getMesa().getJugador(i).getNombre(), punt);
                    }
                }
                break;
        }
        List l = sesion.getResultados();
        l.add(0, mod);
        return l;
    }

    public int getEvaluar(int i, int j) {
        return sesion.getMesa().getJugador(i).getJugada(j).getMano().evaluar()%100;
    }

    public int getEvaluarCroupier(int mod) {
        ManoBkjk m = sesion.getMesa().getCroupier().getMano();
        if (mod == 0) {
            if (m.getCarta(1).getNum() == 1) return 11;
            else return m.getCarta(1).getNum();
        }
        else return m.evaluar()%100;
    }

    public List getInformacion() {
        List l = new ArrayList();
        int cart = sesion.getMesa().getCroupier().getMano().getNumCartas();
        l.add(cart);
        for (int i = 0; i < cart; ++i) {
            Carta c = sesion.getMesa().getCroupier().getMano().getCarta(i);
            if (!c.esVisible()) l.add(1);
            else {
                l.add(0);
                l.add(getPalo(c));
                l.add(c.getNum());
            }
        }
        int jug = sesion.getMesa().getNumJugadores();
        l.add(jug);
        for (int i = 0; i < jug; ++i) {
            int jugadas = sesion.getMesa().getJugador(i).getJugadasActivas();
            l.add(jugadas);
            for (int j = 0; j < jugadas; ++j) {
                int cartas = sesion.getMesa().getJugador(i).getJugada(j).getMano().getNumCartas();
                l.add(cartas);
                for (int k = 0; k < cartas; ++k) {
                    Carta c = sesion.getMesa().getJugador(i).getJugada(j).getMano().getCarta(k);
                    if (!c.esVisible()) l.add(1);
                    else {
                        l.add(0);
                        l.add(getPalo(c));
                        l.add(c.getNum());
                    }
                }
            }
        }

        return l;
    }

    private int getPalo(Carta c) {
        int palo;
        if (c.getPalo() == Carta.Palos.CORAZON) palo = 1;
        else if (c.getPalo() == Carta.Palos.DIAMANTE) palo = 2;
        else if (c.getPalo() == Carta.Palos.PICA) palo = 3;
        else if (c.getPalo() == Carta.Palos.TREBOL) palo = 4;
        else  palo = 0;
        return palo;
    }
}
